<template>
  <div id="appChatView">
    <!-- 顶部栏 -->
    <div class="top-bar">
      <div class="app-name">{{ appInfo?.appName }}</div>
      <a-space>
        <a-button class="deploy-btn" @click="handleDetailApp">
          <template #icon> <InfoCircleOutlined /> </template>应用详情
        </a-button>
        <a-button @click="handleDownloadCode" :loading="downloadLoading" :disabled="!previewUrl">
          <template #icon> <DownloadOutlined /> </template>下载代码</a-button
        >
        <a-popconfirm
          v-if="isOwner"
          title="确认部署该应用吗？"
          ok-text="确定"
          cancel-text="取消"
          @confirm="handleDeployApp"
        >
          <a-button type="primary" class="deploy-btn" :loading="deployLoading" :disabled="!isOwner">
            <template #icon>
              <CloudUploadOutlined />
            </template>
            部署应用
          </a-button>
        </a-popconfirm>
      </a-space>
    </div>

    <!-- 核心内容 -->
    <div class="core-content">
      <!-- 对话区域 -->
      <div class="chat-area">
        <div class="message-list" ref="messageList" @scroll="handleMoreHistory">
          <div v-if="hasMoreHistory && showLoadMore" class="load-more-btn">
            <a-button @click="loadMoreHistory" :loading="loadingHistory" size="small" type="link"
              >加载更多历史记录</a-button
            >
          </div>
          <div
            v-for="(msg, index) in messages"
            :key="index"
            :class="['message', msg.role === 'user' ? 'user-message' : 'ai-message']"
          >
            <!-- 头像 -->
            <img v-if="msg.role === 'ai'" class="avatar" src="@/assets/ai.png" alt="AI" />
            <div v-if="msg.role === 'user'" class="message-content">{{ msg.content }}</div>
            <MarkdownRendered v-else :content="msg.content" class="message-content" />
            <img
              v-if="msg.role === 'user'"
              class="avatar"
              src="https://cdn-icons-png.flaticon.com/512/9131/9131529.png"
              alt="User"
            />
          </div>
        </div>

        <!-- 输入框 -->
        <div class="input-area">
          <a-tooltip v-if="!isOwner" title="仅应用所有者可以发送消息">
            <a-textarea
              class="input-message"
              v-model:value="inputMessage"
              placeholder="输入您的消息..."
              :auto-size="{ maxRows: 10 }"
              @press-enter="sendMessage"
              :disabled="!isOwner"
            />
          </a-tooltip>
          <a-textarea
            v-else
            class="input-message"
            v-model:value="inputMessage"
            placeholder="输入您的消息..."
            :auto-size="{ maxRows: 10 }"
            @press-enter="sendMessage"
            :disabled="!isOwner"
          />
          <a-button type="primary" @click="sendMessage" :loading="isSend" :disabled="!isOwner">
            <template #icon>
              <SendOutlined />
            </template>
          </a-button>
        </div>
      </div>

      <!-- 网页预览区域 -->
      <div class="preview-area">
        <div class="preview-content">
          <a-spin v-if="isSend" tip="正在加载..." size="large"></a-spin>
          <div v-else-if="!previewUrl" class="preview-placeholder">
            <div class="placeholder-icon">🌐</div>
            <p>网站文件生成完成后将在这里展示</p>
          </div>
          <iframe
            v-else
            :src="previewUrl"
            width="100%"
            height="100%"
            frameborder="0"
            scrolling="yes"
            style="border: 0; width: 100%; height: 100%"
          ></iframe>
        </div>
      </div>
    </div>

    <a-modal v-model:open="openDetailsModal" title="应用详情" :footer="null" style="width: 400px">
      <!-- <a-table :columns="columns" :data-source="dataSource" bordered></a-table> -->
      <p>
        <strong>作者：</strong>
        <span style="margin-left: 50px">
          <a-image
            :src="appInfo?.user?.userAvatar"
            alt="User Avatar"
            style="width: 30px; height: 30px; border-radius: 50%; margin-right: 10px"
          />
          {{ appInfo?.user?.userName }}
        </span>
      </p>
      <p>
        <strong>创建时间：</strong
        ><span style="margin-left: 20px">{{
          dayjs(appInfo?.createTime).format('YYYY-MM-DD HH:mm:ss')
        }}</span>
      </p>
      <div class="modal-actions">
        <a-space>
          <a-button @click="closeModal">关闭</a-button>
          <a-button type="primary" @click="handleEditApp" :disabled="!isOwner">编辑</a-button>
        </a-space>
      </div>
    </a-modal>

    <!-- 部署成功弹窗 -->
    <a-modal v-model:open="openDeployModal" title="部署成功" :centered="true" :footer="null">
      <div class="deploy-modal">
        <div class="success-icon">
          <CheckCircleTwoTone
            two-tone-color="#52c41a"
            style="margin-bottom: 20px; font-size: 80px"
          />
        </div>
        <p>部署成功</p>
        <p>你的网站已经成功部署，可以通过以下链接访问：</p>
        <a-input-group compact>
          <a-input v-model:value="websiteLink" :disabled="true" style="width: calc(100% - 200px)" />
          <a-tooltip title="点击复制网址">
            <a-button v-copy="websiteLink">
              <template #icon><CopyOutlined /></template>
            </a-button>
          </a-tooltip>
        </a-input-group>
        <div class="modal-actions">
          <a-space>
            <a-button @click="closeModal">关闭</a-button>
            <a-button type="primary" @click="visitWebsite">访问网站</a-button>
          </a-space>
        </div>
      </div>
    </a-modal>
  </div>

  <!-- 编辑应用弹窗 -->
  <AppEditModal
    v-if="openEditModal"
    :app="appInfo"
    v-model:edit-loading="editLoading"
    v-model:openEditModal="openEditModal"
    @handle-edit-app="saveEditApp"
  />
</template>

<script setup lang="ts">
import { ref, nextTick, reactive, onMounted, computed } from 'vue'
import { Button as AButton, Input as AInput } from 'ant-design-vue'
import { message } from 'ant-design-vue'
import {
  CheckCircleTwoTone,
  CopyOutlined,
  CloudUploadOutlined,
  InfoCircleOutlined,
  DownloadOutlined,
  CheckCircleOutlined,
} from '@ant-design/icons-vue'
import { useRoute } from 'vue-router'
import { getAppVoById, chatToGenCode, deployApp, downloadAppCode } from '@/api/appController'
import { SendOutlined } from '@ant-design/icons-vue'
import MarkdownRendered from '@/components/MarkdownRendered.vue'
import { serveStaticResource } from '@/api/staticResourceController'
import { updateAppByAdmin, updateApp } from '@/api/appController'
import dayjs from 'dayjs'
import AppEditModal from '@/components/AppEditModal.vue'
import { listAppChatHistory } from '@/api/chatHistoryController'
import { useLoginUserStore } from '@/stores/loginUser'

interface Messages {
  role: 'user' | 'ai'
  content: string
  loading?: boolean
}

const messages = ref<Messages[]>([]) // 消息列表

const route = useRoute()
const appId = ref<string>('')
const appInfo = ref<API.AppVo>()

const inputMessage = ref('')
const showPreview = ref(false)
const previewUrl = ref('')
const messageList = ref<HTMLElement | null>(null)
const websiteLink = ref('')

const editLoading = ref<boolean>(false) // 保存按钮loading状态
const deployLoading = ref<boolean>(false)
const downloadLoading = ref<boolean>(false) // 下载按钮loading状态
const openDeployModal = ref(false)
const openDetailsModal = ref(false)
const openEditModal = ref(false)
const isSend = ref(false) // 是否正在发送消息
const isFirst = ref(false) // 是否是第一次发送消息

// 加载历史相关
const loadingHistory = ref<boolean>(false)
const lastCreateTime = ref<string>()
const hasMoreHistory = ref<boolean>(false)
const historyLoaded = ref<boolean>(false)
const showLoadMore = ref<boolean>(false)

const formState = reactive<API.AppVo>({
  appName: '',
  cover: '',
  initPrompt: '',
  deployKey: '',
  deployedTime: '',
  priority: 0,
  userId: 0,
  codeGenType: '',
})

const loginUserStore = useLoginUserStore()

// 获取更多历史记录
const handleMoreHistory = (e: Event) => {
  const target = e.target as HTMLElement
  showLoadMore.value = target.scrollTop < 50
}

// 获取应用详情
const getAppInfo = async () => {
  const id = route.params.id as string
  if (!id) {
    message.error('应用ID不存在')
    return
  }

  appId.value = id

  try {
    const res = await getAppVoById({ id: id as unknown as number })
    if (res.data.code === 0 && res.data.data) {
      appInfo.value = res.data.data

      // 首先判断是不是有历史数据 加载历史数据
      await loadChatHistory()
      // 如果有历史数据直接获取页面url
      if (messages.value.length >= 2) {
        updatePreviewUrl()
      }

      // 查看对话，不是第一次
      console.log(route.query.view, 'router.query.view')
      const isView = route.query.view === '1'
      console.log(isView, 'isView')

      // 自动发送初始提示词
      // if (!isView && appInfo.value.initPrompt && !isFirst.value) {
      if (historyLoaded.value && appInfo.value.initPrompt && messages.value.length === 0) {
        isFirst.value = true
        // 第一次进入对话页面
        await sendInitialMessage(appInfo.value.initPrompt)
      }
      scrollToBottom()
    }
  } catch (err: any) {
    message.error(err.message)
  }
}

// 是否是本人的应用
const isOwner = computed(() => {
  return appInfo.value?.userId === loginUserStore.loginUser?.id
})

// 是否是管理员
const isAdmin = computed(() => {
  return loginUserStore.loginUser?.userRole === 'admin'
})

// 发送初始提示词
const sendInitialMessage = async (prompt: string) => {
  messages.value.push({ role: 'user', content: prompt })
  const messageIndex = messages.value.length
  messages.value.push({ role: 'ai', content: '正在思考中...', loading: true })

  await generateCode(prompt, messageIndex)
}

// 生成代码
const generateCode = async (prompt: string, messageIndex: number) => {
  let source: EventSource | null = null

  let isStreaming = ref(true) // 是否正在流式响应

  try {
    let buffer = '' // 缓存，用于非流式模式
    let finallyContent = '' // 存储最终结果
    let content = '' // 流式拼接内容

    const params = new URLSearchParams({
      appId: appId.value || '',
      message: prompt,
    })
    // 注意：EventSource 只能 GET，且 withCredentials 要放在 options 对象
    const source = new EventSource(
      `${import.meta.env.VITE_API_BASE_URL}/app/chat/gen/code?${params}`,
      {
        // const source = new EventSource(`http://localhost:8123/api/app/chat/gen/code?${params}`, {
        // const source = new EventSource(`http://oq1pv0210672.vicp.fun/api/app/chat/gen/code?${params}`,{
        withCredentials: true,
      },
    )

    isSend.value = true

    // 处理接收到的信息
    source.onmessage = (event) => {
      try {
        if (isStreaming.value) {
          content += JSON.parse(event.data).d // 拿到正确的数据并且 拼接流式数据
          // console.log('流式数据',content);

          messages.value[messageIndex].content = content
          messages.value[messageIndex].loading = false
        } else {
          buffer += event.data // // 不实时显示：只在 buffer 拼接，等 end 事件再把 buffer 写入 UI
        }
      } catch (errorData) {
        message.error('解析数据失败：' + errorData)
        console.log(errorData)
      }
    }

    // 监听后端发送的 done 事件
    source.addEventListener('done', (event) => {
      isStreaming.value = false // 生成结束，关闭流式模式
      // finallyContent = event.data || buffer || finallyContent // 最终结果：优先级：event.data > buffer > finallyContent
      // messages.value[messageIndex].content = event.data || buffer || messages.value[messageIndex].content
      isSend.value = false
      source.close()

      updatePreviewUrl()
    })

    // 监听后端发送的 error 事件(后端限流等错误)
    source.addEventListener('busines-error', (event) => {
      if (!isStreaming.value) return

      try {
        const errorData = JSON.parse(event.data) // 解析错误信息
        console.error('SSE业务错误事件:', errorData)

        // 具体的错误信息
        messages.value[messageIndex].content = errorData.message || '生成过程中出现错误'
        messages.value[messageIndex].loading = false

        isStreaming.value = false // 生成结束，关闭流式模式
        source.close()
      } catch (errorData) {
        console.error('解析错误事件失败:', errorData, '原始数据:', event.data)
      }
    })

    // 错误处理
    source.onerror = (errorData: any) => {
      if (!isStreaming.value) return
      if (source.readyState === EventSource.CLOSED) {
        isStreaming.value = false // 生成结束，关闭流式模式
        source.close()

        updatePreviewUrl()
      } else {
        message.error('生成失败')
        isStreaming.value = false // 生成结束，关闭流式模式
        source.close()
      }
    }
  } catch (error: any) {
    message.error(error.message)
  }
}

// const generateCode = async (prompt: string,messageIndex: number) => {
//   isSend.value = true
//   const fakeResponse = "这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。这是一个模拟的流式输出效果，完全不调用后端接口，用来节省成本。你可以根据需求自定义内容。"
//   let content = ""
//   let i = 0

//   const timer = setInterval(() => {
//     if (i < fakeResponse.length) {
//       content += fakeResponse[i]
//       messages.value[messageIndex].content = content
//       messages.value[messageIndex].loading = false
//       i++
//     } else {
//       clearInterval(timer)
//       isSend.value = false // 流式结束
//     }
//   }, 100) // 每100ms输出一个字符，可调快/慢
// }

// 发送消息
const sendMessage = async () => {
  const prompt = inputMessage.value.trim()
  if (prompt) {
    // 添加用户消息
    messages.value.push({ role: 'user', content: prompt })

    const messageIndex = messages.value.length
    messages.value.push({ role: 'ai', content: '正在思考中...', loading: true })

    generateCode(prompt, messageIndex)
    inputMessage.value = ''
    scrollToBottom()
  }
}

const scrollToBottom = () => {
  nextTick(() => {
    if (messageList.value) {
      messageList.value.scrollTop = messageList.value.scrollHeight
    }
  })
}

// 应用详情
const handleDetailApp = () => {
  openDetailsModal.value = true
}

// 下载代码
const handleDownloadCode = async () => {
  if (!appId.value) {
    message.error('应用不存在')
    return
  }
  downloadLoading.value = true
  try {
    const res = await downloadAppCode({ appId: appId.value }, { responseType: 'blob' })
    debugger
    if (res.status === 200 && res.data) {
      const blob = new Blob([res.data], { type: 'application/zip' })
      const url = URL.createObjectURL(blob)
      const a = document.createElement('a')
      a.href = url
      a.download = `app-${appId.value}.zip`
      a.click()
      URL.revokeObjectURL(url)
    } else {
      message.error(res.data.message || '下载失败！')
    }
  } catch (error) {
    message.error('下载失败！' + error)
  } finally {
    downloadLoading.value = false
  }
}

// 应用部署
const handleDeployApp = async () => {
  if (!isOwner.value) {
    message.error('只有应用所有者才能部署应用')
    return
  }
  // 部署应用逻辑
  // console.log('Deploying app...')
  // deployLoading.value = true

  // try {
  //   // 模拟部署过程
  //   setTimeout(() => {
  //     deployLoading.value = false
  //     openDeployModal.value = true
  //     message.success('部署成功！')
  //   }, 2000)
  // } catch (error) {
  //   console.log('部署失败：' + error)
  //   message.error('部署失败！请重试')
  //   deployLoading.value = false
  // } finally {
  //   // deployLoading.value = false
  // }

  if (!appId.value) {
    message.error('应用不存在')
    return
  }

  deployLoading.value = true
  try {
    const res = await deployApp({ appId: String(appInfo.value?.id) })

    if (res.data.code === 0 && res.data.data) {
      websiteLink.value = res.data.data
      openDeployModal.value = true
      message.success('部署成功！')
    } else {
      message.success('部署失败！')
    }
  } catch (error) {
    message.error('部署失败！' + error)
  } finally {
    deployLoading.value = false
  }
}

// 访问网站
const visitWebsite = () => {
  // console.log('Visit website')
  if (!websiteLink.value) {
    message.error('网站链接不存在')
    return
  } else {
    window.open(websiteLink.value, '_blank') // 在新标签页中打开链接
  }
}

// 编辑应用
const handleEdit = () => {
  openEditModal.value = true
}

// 删除应用
const handleDelete = async () => {
  if (!appId.value) {
    message.error('应用不存在')
    return
  }
}

const closeModal = () => {
  openDeployModal.value = false
  openDetailsModal.value = false
}

const handleEditApp = () => {
  openDetailsModal.value = false
  openEditModal.value = true
}

// 更新预览路径
const updatePreviewUrl = async () => {
  if (!appInfo.value) return
  try {
    const res = await serveStaticResource({ appId: String(appInfo.value.id) })
    previewUrl.value = res.request.responseURL
  } catch (error) {
    console.log(error, 'error')
  }
}

// 保存应用修改
const saveEditApp = async (app: API.AppVo) => {
  try {
    let res
    if (isAdmin.value) {
      res = await updateAppByAdmin(app)
    } else {
      res = await updateApp(app)
    }
    if (res.data.code === 0 && res.data.data) {
      editLoading.value = false
      message.success('修改成功')
      openEditModal.value = false
      // getAppList()
      getAppInfo()
    } else {
      message.error('修改失败' + res.data.message)
    }
  } catch (error: any) {
    console.log(error, '修改失败')
    message.error('修改失败' + error.message)
  } finally {
    editLoading.value = false
  }
}

// 加载历史对话
const loadChatHistory = async (isLoadMore?: boolean) => {
  if (!appInfo.value || loadingHistory.value) return
  loadingHistory.value = true
  try {
    const params: API.listAppChatHistoryParams = {
      appId: appId.value,
      pageSize: 10,
    }

    // 如果是加载更多，传递最后一条消息的创建时间为游标
    if (isLoadMore && lastCreateTime.value) {
      params.lastCreateTime = lastCreateTime.value
    }

    const res = await listAppChatHistory(params)
    if (res.data.code === 0 && res.data.data) {
      const chatHistory = res.data.data.records || []
      if (chatHistory.length > 0) {
        // 将历史对话转换为消息格式，并添加到消息列表中
        const historyMessages: Messages[] = chatHistory
          .map((chat) => ({
            role: (chat.messageType === 'user' ? 'user' : 'ai') as 'user' | 'ai',
            content: chat.message || '',
            createTime: chat.createTime,
          }))
          .reverse()
        if (isLoadMore) {
          messages.value.unshift(...historyMessages)
        } else {
          // 初始化加载，直接设置消息列表
          messages.value = historyMessages
        }

        // 更新最后一条消息的创建时间
        lastCreateTime.value = chatHistory[chatHistory.length - 1].createTime

        // 判断是否还有更多历史记录
        hasMoreHistory.value = chatHistory.length === 10
      } else {
        hasMoreHistory.value = false
      }
      historyLoaded.value = true
    }
  } catch (error) {
    console.error('加载历史对话失败:', error)
    message.error('加载历史对话失败')
  } finally {
    loadingHistory.value = false
  }
}

const loadMoreHistory = async () => {
  await loadChatHistory(true)
}

onMounted(() => {
  getAppInfo()
})
</script>

<style scoped>
#appChatView {
  height: 100vh;
  display: flex;
  flex-direction: column;
  font-family: 'Helvetica Neue', Arial, sans-serif;
  max-height: calc(100vh - 88px);
  background: #fff;
  padding: 10px 25px;
  margin: 10px;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
}

/* 顶部栏 */
.top-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 20px;
  /* background-color: #1890ff; */
  color: #333;
  font-size: 18px;
  font-weight: bold;
}

/* 核心区域 */
.core-content {
  flex: 1;
  display: flex;
  overflow: hidden; /* 防止整体页面滚动 */
}

/* 左侧聊天区 */
.chat-area {
  width: 35%;
  display: flex;
  flex-direction: column;
  border-right: 1px solid #ddd;
}
.message-list {
  flex: 1;
  overflow-y: auto; /* 只让消息区滚动 */
  padding: 15px;
  /* background: #f9f9f9; */
}
.message {
  display: flex;
  align-items: flex-end;
  margin-bottom: 12px;
}
.ai-message {
  justify-content: flex-start;
}
.user-message {
  justify-content: flex-end;
}
.message-content {
  max-width: 80%;
  padding: 10px 14px;
  border-radius: 12px;
  background-color: #e6f7ff;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.user-message .message-content {
  background-color: #d9f7be;
}
.avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  margin: 0 8px;
}

/* 输入框 */
.input-area {
  display: flex;
  padding: 10px;
  border-top: 1px solid #ddd;
  background: #fff;
  align-items: center;
}
.input-area .input-message {
  flex: 1;
  margin-right: 10px;
  padding: 12px 20px 12px 20px;
  height: 50px;
  border-radius: 25px;
  font-size: 16px;
  box-sizing: border-box;
}

.input-area .input-message::-webkit-scrollbar {
  width: 6px;
}
.input-area .input-message::-webkit-scrollbar-track {
  background: transparent;
  border-radius: 10px;
  padding: 50px 0;
}

.input-area .input-message::-webkit-scrollbar-thumb {
  background: #bfbfbf;
  border-radius: 4px;
}

/* 右侧预览区 */
.preview-area {
  width: 65%;
  padding: 20px;
  /* background-color: #fafafa; */
  overflow-y: auto;
}
.preview-content {
  border: 1px solid #ddd;
  border-radius: 12px;
  padding: 20px;
  background: #fff;
  height: 100%;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
  position: relative;
}
.preview-content .ant-spin {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
.preview-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: #666;
  font-size: 20px;
}

.preview-card {
  padding: 16px;
  margin: 16px 0;
  border-radius: 8px;
  background: linear-gradient(135deg, #91d5ff, #1890ff);
  color: #fff;
}
.preview-buttons {
  display: flex;
  gap: 12px;
}
.btn {
  padding: 8px 14px;
  border: none;
  border-radius: 6px;
  background-color: #1890ff;
  color: #fff;
  cursor: pointer;
}
.btn:hover {
  background-color: #40a9ff;
}

.deploy-modal {
  text-align: center;
}

.modal-actions {
  margin-top: 20px;
  gap: 20px;
}

.load-more-btn {
  text-align: center;
}
</style>
